﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using AutoPoco;
using AutoPoco.DataSources;
using AutoPoco.Engine;
using DataGeneration.Makers;

namespace DataGeneration
{
    class Program
    {
        private static QuizzMeEntities _entities;
        private static IGenerationSessionFactory _factory;
        private static IGenerationSession _session;

        [ImportMany]
        public Lazy<IMaker, IMakerAttribute>[] Makers { get; set; }

        static void Main(string[] args)
        {
            _entities = new QuizzMeEntities();

            InitAutoPoco();
            var p = new Program();
            p.Compose();
            p.Run();
            Console.ReadLine();
        }

        private void Compose()
        {
            var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var container = new CompositionContainer(catalog);
            container.ComposeExportedValue(_entities);
            container.ComposeExportedValue(_session);
            container.ComposeParts(this);
        }

        private void Run()
        {
            var groups = Makers.GroupBy(x => x.Metadata.Priority).OrderByDescending(x => x.Key);
            ClearTables(groups);
            FillTables(groups);
            Logger.LogLow("%yellow%EVERY THING COMPLETE, PRESS KEY");
        }

        private static void FillTables(IEnumerable<IGrouping<int, Lazy<IMaker, IMakerAttribute>>> groups)
        {
            foreach (IGrouping<int, Lazy<IMaker, IMakerAttribute>> grouping in groups.Reverse())
            {
                foreach (Lazy<IMaker, IMakerAttribute> sender in grouping)
                {
                    Console.WriteLine("{0}: {1}", sender.Metadata.Priority, sender.Value.GetType().Name);
                    sender.Value.Apply();
                }
                _entities.SaveChanges();
            }
        }

        private static void ClearTables(IEnumerable<IGrouping<int, Lazy<IMaker, IMakerAttribute>>> groups)
        {
            foreach (Lazy<IMaker, IMakerAttribute> sender in groups.SelectMany(grouping => grouping))
            {
                Console.WriteLine("{0}: {1}", sender.Metadata.Priority, sender.Value.GetType().Name);
                sender.Value.Delete();

                _entities.SaveChanges();
            }
        }

        private static void InitAutoPoco()
        {
            _factory = AutoPocoContainer.Configure(
                x =>
                {
                    x.Conventions(c => c.UseDefaultConventions());

                    x.AddFromAssemblyContainingType<Difficulty>();

                    x.AddFromAssemblyContainingType<Theme>();
                    //x.Include<Theme>().Setup(t => t.name).Use<FirstNameSource>();

                    x.AddFromAssemblyContainingType<User>();
                    x.Include<User>()
                        .Setup(u => u.Difficulty).Use<RandomSqlRowDataSource<Difficulty>>(_entities.Difficulty)
                        .Setup(u => u.score).Use<ValueSource<int>>(0);

                    x.AddFromAssemblyContainingType<Quizz>();
                    x.Include<Quizz>()
                        .Setup(q => q.Theme).Use<RandomSqlRowDataSource<Theme>>(_entities.Theme);

                    x.AddFromAssemblyContainingType<Question>();
                    x.Include<Question>()
                        .Setup(q => q.Theme).Use<RandomSqlRowDataSource<Theme>>(_entities.Theme)
                        .Setup(q => q.time).Use<ValueSource<int>>(10);

                    x.AddFromAssemblyContainingType<QuizzPart>();
                    x.Include<QuizzPart>()
                        .Setup(q => q.Quizz).Use<RandomSqlRowDataSource<Quizz>>(_entities.Quizz)
                        .Setup(q => q.Question).Use<RandomSqlRowDataSource<Question>>(_entities.Question)
                        //.Setup(q => q.Question).Use<RandomSqlRowIdSource<int, QuizzPart>>(_entities.Quizzs, new Func<Quizz, int>(t => t.quizzId) )
                        ;

                    x.AddFromAssemblyContainingType<Result>();
                    //x.Include<Result>()
                    //    .Setup(q => q.Quizz).Use<RandomSqlRowDataSource<Quizz>>(_entities.Quizz)
                    //    .Setup(q => q.User).Use<RandomSqlRowDataSource<User>>(_entities.User)
                    //    .Setup(q => q.score).Use<DefaultSource<>>(0, 100);
                });
            _session = _factory.CreateSession();
        }
    }
}

